xtask\tasks\fuzz/
init_from_template.rs1use super::cargo_package_metadata;
7use anyhow::Context;
8
9#[derive(Clone, clap::ValueEnum)]
10pub enum Template {
11 ChipsetDevice,
13 Basic,
15}
16
17pub(super) fn init_from_template(
18 ctx: &crate::XtaskCtx,
19 package: String,
20 template: Template,
21) -> Result<(), anyhow::Error> {
22 let selected_crate = 'selected_crate: {
23 let cargo_tomls = ignore::Walk::new(&ctx.root).filter_map(|entry| match entry {
24 Ok(entry) if entry.file_name() == "Cargo.toml" => Some(entry.into_path()),
25 Err(err) => {
26 log::error!("error when walking over subdirectories: {}", err);
27 None
28 }
29 _ => None,
30 });
31
32 for cargo_toml_path in cargo_tomls {
33 let manifest = cargo_toml::Manifest::<cargo_package_metadata::PackageMetadata>::from_path_with_metadata(
34 &cargo_toml_path,
35 )?;
36
37 if manifest
38 .package
39 .as_ref()
40 .map(|x| x.name())
41 .unwrap_or_default()
42 == package
43 {
44 break 'selected_crate cargo_toml_path;
45 }
46 }
47
48 anyhow::bail!("unknown crate '{}'", package)
49 };
50
51 let new_fuzz_target = format!("fuzz_{}", package);
52 let new_fuzz_dir = selected_crate.parent().unwrap().join("fuzz");
53
54 if new_fuzz_dir.exists() {
56 anyhow::bail!("{} already has a `fuzz/` folder!", package)
57 }
58 fs_err::create_dir(&new_fuzz_dir)?;
59 fs_err::write(
60 new_fuzz_dir.join("Cargo.toml"),
61 match template {
62 Template::Basic => include_str!("./templates/basic.template.toml"),
63 Template::ChipsetDevice => include_str!("./templates/chipset_device.template.toml"),
64 }
65 .to_string()
66 .replacen("$FUZZ_CRATE_NAME$", &new_fuzz_target, usize::MAX)
67 .replacen("$PARENT$", &package, usize::MAX)
68 .replacen("$FUZZ_TARGET_NAME$", &new_fuzz_target, usize::MAX),
69 )?;
70 fs_err::write(
71 new_fuzz_dir.join(format!("{}.rs", new_fuzz_target)),
72 match template {
73 Template::Basic => include_str!("./templates/basic.template.rs"),
74 Template::ChipsetDevice => include_str!("./templates/chipset_device.template.rs"),
75 },
76 )?;
77
78 let new_workspace_entry = new_fuzz_dir.strip_prefix(&ctx.root)?.display().to_string();
80 let root_toml_raw = fs_err::read_to_string(ctx.root.join("Cargo.toml"))?;
81 let mut root_toml = root_toml_raw
82 .parse::<toml_edit::DocumentMut>()
83 .context("invalid root workspace Cargo.toml")?;
84 let members = &mut root_toml["workspace"]["members"].as_array_mut().unwrap();
85 members.push_formatted(toml_edit::Value::from(new_workspace_entry).decorated("\n ", ""));
88 fs_err::write(ctx.root.join("Cargo.toml"), root_toml.to_string())?;
89
90 Ok(())
91}